home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 August: Tool Chest / Dev.CD Aug 95 TC / Dev.CD Aug 95 TC.toast / Tool Chest / Development Tools & Languages / Dylan Related / Marlais / Marlais 0.5.9-portable sources / gc / mach_dep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-15  |  13.4 KB  |  390 lines  |  [TEXT/ttxt]

  1. /* 
  2.  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3.  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
  4.  *
  5.  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  6.  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  7.  *
  8.  * Permission is hereby granted to use or copy this program
  9.  * for any purpose,  provided the above notices are retained on all copies.
  10.  * Permission to modify the code and to distribute modified code is granted,
  11.  * provided the above notices are retained, and a notice that the code was
  12.  * modified is included with the above copyright notice.
  13.  */
  14. /* Boehm, December 12, 1994 5:03 pm PST */
  15. # include "gc_priv.h"
  16. # include <stdio.h>
  17. # include <setjmp.h>
  18. # if defined(OS2) || defined(CX_UX)
  19. #   define _setjmp(b) setjmp(b)
  20. #   define _longjmp(b,v) longjmp(b,v)
  21. # endif
  22. # ifdef AMIGA
  23. #   include <dos.h>
  24. # endif
  25.  
  26. #if defined(__MWERKS__) && !defined(POWERPC)
  27.  
  28. asm static void PushMacRegisters()
  29. {
  30.     sub.w   #4,sp                   // reserve space for one parameter.
  31.     move.l  a2,(sp)
  32.     jsr        GC_push_one
  33.     move.l  a3,(sp)
  34.     jsr        GC_push_one
  35.     move.l  a4,(sp)
  36.     jsr        GC_push_one
  37.     // skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
  38.     move.l  d2,(sp)
  39.     jsr        GC_push_one
  40.     move.l  d3,(sp)
  41.     jsr        GC_push_one
  42.     move.l  d4,(sp)
  43.     jsr        GC_push_one
  44.     move.l  d5,(sp)
  45.     jsr        GC_push_one
  46.     move.l  d6,(sp)
  47.     jsr        GC_push_one
  48.     move.l  d7,(sp)
  49.     jsr        GC_push_one
  50.     add.w   #4,sp                   // fix stack.
  51.     rts
  52. }
  53.  
  54. #endif /* __MWERKS__ */
  55.  
  56. /* Routine to mark from registers that are preserved by the C compiler. */
  57. /* This must be ported to every new architecture.  There is a generic   */
  58. /* version at the end, that is likely, but not guaranteed to work       */
  59. /* on your architecture.  Run the test_setjmp program to see whether    */
  60. /* there is any chance it will work.                                    */
  61.  
  62. void GC_push_regs()
  63. {
  64. #       ifdef RT
  65.       register long TMP_SP; /* must be bound to r11 */
  66. #       endif
  67. #       ifdef VAX
  68.       /* VAX - generic code below does not work under 4.2 */
  69.       /* r1 through r5 are caller save, and therefore     */
  70.       /* on the stack or dead.                            */
  71.       asm("pushl r11");     asm("calls $1,_GC_push_one");
  72.       asm("pushl r10");     asm("calls $1,_GC_push_one");
  73.       asm("pushl r9");    asm("calls $1,_GC_push_one");
  74.       asm("pushl r8");    asm("calls $1,_GC_push_one");
  75.       asm("pushl r7");    asm("calls $1,_GC_push_one");
  76.       asm("pushl r6");    asm("calls $1,_GC_push_one");
  77. #       endif
  78. #       if defined(M68K) && (defined(SUNOS4) || defined(NEXT))
  79.     /*  M68K SUNOS - could be replaced by generic code */
  80.       /* a0, a1 and d1 are caller save          */
  81.       /*  and therefore are on stack or dead.   */
  82.     
  83.       asm("subqw #0x4,sp");        /* allocate word on top of stack */
  84.  
  85.       asm("movl a2,sp@");    asm("jbsr _GC_push_one");
  86.       asm("movl a3,sp@");    asm("jbsr _GC_push_one");
  87.       asm("movl a4,sp@");    asm("jbsr _GC_push_one");
  88.       asm("movl a5,sp@");    asm("jbsr _GC_push_one");
  89.       /* Skip frame pointer and stack pointer */
  90.       asm("movl d1,sp@");    asm("jbsr _GC_push_one");
  91.       asm("movl d2,sp@");    asm("jbsr _GC_push_one");
  92.       asm("movl d3,sp@");    asm("jbsr _GC_push_one");
  93.       asm("movl d4,sp@");    asm("jbsr _GC_push_one");
  94.       asm("movl d5,sp@");    asm("jbsr _GC_push_one");
  95.       asm("movl d6,sp@");    asm("jbsr _GC_push_one");
  96.       asm("movl d7,sp@");    asm("jbsr _GC_push_one");
  97.  
  98.       asm("addqw #0x4,sp");        /* put stack back where it was    */
  99. #       endif
  100.  
  101. #       if defined(M68K) && defined(HP)
  102.     /*  M68K HP - could be replaced by generic code */
  103.       /* a0, a1 and d1 are caller save.  */
  104.     
  105.       asm("subq.w &0x4,%sp");    /* allocate word on top of stack */
  106.  
  107.       asm("mov.l %a2,(%sp)"); asm("jsr _GC_push_one");
  108.       asm("mov.l %a3,(%sp)"); asm("jsr _GC_push_one");
  109.       asm("mov.l %a4,(%sp)"); asm("jsr _GC_push_one");
  110.       asm("mov.l %a5,(%sp)"); asm("jsr _GC_push_one");
  111.       /* Skip frame pointer and stack pointer */
  112.       asm("mov.l %d1,(%sp)"); asm("jsr _GC_push_one");
  113.       asm("mov.l %d2,(%sp)"); asm("jsr _GC_push_one");
  114.       asm("mov.l %d3,(%sp)"); asm("jsr _GC_push_one");
  115.       asm("mov.l %d4,(%sp)"); asm("jsr _GC_push_one");
  116.       asm("mov.l %d5,(%sp)"); asm("jsr _GC_push_one");
  117.       asm("mov.l %d6,(%sp)"); asm("jsr _GC_push_one");
  118.       asm("mov.l %d7,(%sp)"); asm("jsr _GC_push_one");
  119.  
  120.       asm("addq.w &0x4,%sp");    /* put stack back where it was    */
  121. #       endif /* M68K HP */
  122.  
  123. #       ifdef AMIGA
  124.     /*  AMIGA - could be replaced by generic code             */
  125.       /* a0, a1, d0 and d1 are caller save */
  126.       GC_push_one(getreg(REG_A2));
  127.       GC_push_one(getreg(REG_A3));
  128.       GC_push_one(getreg(REG_A4));
  129.       GC_push_one(getreg(REG_A5));
  130.       GC_push_one(getreg(REG_A6));
  131.       /* Skip stack pointer */
  132.       GC_push_one(getreg(REG_D2));
  133.       GC_push_one(getreg(REG_D3));
  134.       GC_push_one(getreg(REG_D4));
  135.       GC_push_one(getreg(REG_D5));
  136.       GC_push_one(getreg(REG_D6));
  137.       GC_push_one(getreg(REG_D7));
  138. #       endif
  139.  
  140. #    if defined(M68K) && defined(MACOS)
  141. #    if defined(THINK_C)
  142. #         define PushMacReg(reg) \
  143.               move.l  reg,(sp) \
  144.               jsr             GC_push_one
  145.       asm {
  146.               sub.w   #4,sp                   ; reserve space for one parameter.
  147.               PushMacReg(a2);
  148.               PushMacReg(a3);
  149.               PushMacReg(a4);
  150.               ; skip a5 (globals), a6 (frame pointer), and a7 (stack pointer)
  151.               PushMacReg(d2);
  152.               PushMacReg(d3);
  153.               PushMacReg(d4);
  154.               PushMacReg(d5);
  155.               PushMacReg(d6);
  156.               PushMacReg(d7);
  157.               add.w   #4,sp                   ; fix stack.
  158.       }
  159. #      undef PushMacReg
  160. #    endif /* THINK_C */
  161. #    if defined(__MWERKS__)
  162.       PushMacRegisters();
  163. #    endif    /* __MWERKS__ */
  164. #   endif    /* MACOS */
  165.  
  166. #       if defined(I386) &&!defined(OS2) &&!defined(SVR4) &&!defined(MSWIN32) && !defined(SCO)
  167.     /* I386 code, generic code does not appear to work */
  168.     /* It does appear to work under OS2, and asms dont */
  169.       asm("pushl %eax");  asm("call _GC_push_one"); asm("addl $4,%esp");
  170.       asm("pushl %ecx");  asm("call _GC_push_one"); asm("addl $4,%esp");
  171.       asm("pushl %edx");  asm("call _GC_push_one"); asm("addl $4,%esp");
  172.       asm("pushl %esi");  asm("call _GC_push_one"); asm("addl $4,%esp");
  173.       asm("pushl %edi");  asm("call _GC_push_one"); asm("addl $4,%esp");
  174.       asm("pushl %ebx");  asm("call _GC_push_one"); asm("addl $4,%esp");
  175. #       endif
  176.  
  177. #       if defined(I386) && defined(MSWIN32)
  178.     /* I386 code, Microsoft variant        */
  179.       __asm  push eax
  180.       __asm  call GC_push_one
  181.       __asm  add esp,4
  182.       __asm  push ebx
  183.       __asm  call GC_push_one
  184.       __asm  add esp,4
  185.       __asm  push ecx
  186.       __asm  call GC_push_one
  187.       __asm  add esp,4
  188.       __asm  push edx
  189.       __asm  call GC_push_one
  190.       __asm  add esp,4
  191.       __asm  push ebp
  192.       __asm  call GC_push_one
  193.       __asm  add esp,4
  194.       __asm  push esi
  195.       __asm  call GC_push_one
  196.       __asm  add esp,4
  197.       __asm  push edi
  198.       __asm  call GC_push_one
  199.       __asm  add esp,4
  200. #       endif
  201.  
  202. #       if defined(I386) && (defined(SVR4) || defined(SCO))
  203.     /* I386 code, SVR4 variant, generic code does not appear to work */
  204.       asm("pushl %eax");  asm("call GC_push_one"); asm("addl $4,%esp");
  205.       asm("pushl %ebx");  asm("call GC_push_one"); asm("addl $4,%esp");
  206.       asm("pushl %ecx");  asm("call GC_push_one"); asm("addl $4,%esp");
  207.       asm("pushl %edx");  asm("call GC_push_one"); asm("addl $4,%esp");
  208.       asm("pushl %ebp");  asm("call GC_push_one"); asm("addl $4,%esp");
  209.       asm("pushl %esi");  asm("call GC_push_one"); asm("addl $4,%esp");
  210.       asm("pushl %edi");  asm("call GC_push_one"); asm("addl $4,%esp");
  211. #       endif
  212.  
  213. #       ifdef NS32K
  214.       asm ("movd r3, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
  215.       asm ("movd r4, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
  216.       asm ("movd r5, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
  217.       asm ("movd r6, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
  218.       asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");
  219. #       endif
  220.  
  221. #       ifdef SPARC
  222.       {
  223.           word GC_save_regs_in_stack();
  224.           
  225.           /* generic code will not work */
  226.           (void)GC_save_regs_in_stack();
  227.       }
  228. #       endif
  229.  
  230. #    ifdef RT
  231.         GC_push_one(TMP_SP);    /* GC_push_one from r11 */
  232.  
  233.         asm("cas r11, r6, r0"); GC_push_one(TMP_SP);    /* r6 */
  234.         asm("cas r11, r7, r0"); GC_push_one(TMP_SP);    /* through */
  235.         asm("cas r11, r8, r0"); GC_push_one(TMP_SP);    /* r10 */
  236.         asm("cas r11, r9, r0"); GC_push_one(TMP_SP);
  237.         asm("cas r11, r10, r0"); GC_push_one(TMP_SP);
  238.  
  239.         asm("cas r11, r12, r0"); GC_push_one(TMP_SP); /* r12 */
  240.         asm("cas r11, r13, r0"); GC_push_one(TMP_SP); /* through */
  241.         asm("cas r11, r14, r0"); GC_push_one(TMP_SP); /* r15 */
  242.         asm("cas r11, r15, r0"); GC_push_one(TMP_SP);
  243. #       endif
  244.  
  245. #       if defined(M68K) && defined(SYSV)
  246.       /*  Once again similar to SUN and HP, though setjmp appears to work.
  247.           --Parag
  248.        */
  249. #        ifdef __GNUC__
  250.         asm("subqw #0x4,%sp");    /* allocate word on top of stack */
  251.   
  252.         asm("movl %a2,%sp@");    asm("jbsr GC_push_one");
  253.         asm("movl %a3,%sp@");    asm("jbsr GC_push_one");
  254.         asm("movl %a4,%sp@");    asm("jbsr GC_push_one");
  255.         asm("movl %a5,%sp@");    asm("jbsr GC_push_one");
  256.         /* Skip frame pointer and stack pointer */
  257.         asm("movl %d1,%sp@");    asm("jbsr GC_push_one");
  258.         asm("movl %d2,%sp@");    asm("jbsr GC_push_one");
  259.         asm("movl %d3,%sp@");    asm("jbsr GC_push_one");
  260.         asm("movl %d4,%sp@");    asm("jbsr GC_push_one");
  261.         asm("movl %d5,%sp@");    asm("jbsr GC_push_one");
  262.         asm("movl %d6,%sp@");    asm("jbsr GC_push_one");
  263.         asm("movl %d7,%sp@");    asm("jbsr GC_push_one");
  264.   
  265.         asm("addqw #0x4,%sp");    /* put stack back where it was    */
  266. #        else /* !__GNUC__*/
  267.         asm("subq.w &0x4,%sp");    /* allocate word on top of stack */
  268.   
  269.         asm("mov.l %a2,(%sp)"); asm("jsr GC_push_one");
  270.         asm("mov.l %a3,(%sp)"); asm("jsr GC_push_one");
  271.         asm("mov.l %a4,(%sp)"); asm("jsr GC_push_one");
  272.         asm("mov.l %a5,(%sp)"); asm("jsr GC_push_one");
  273.         /* Skip frame pointer and stack pointer */
  274.         asm("mov.l %d1,(%sp)"); asm("jsr GC_push_one");
  275.         asm("mov.l %d2,(%sp)"); asm("jsr GC_push_one");
  276.         asm("mov.l %d3,(%sp)"); asm("jsr GC_push_one");
  277.         asm("mov.l %d4,(%sp)"); asm("jsr GC_push_one");
  278.         asm("mov.l %d5,(%sp)"); asm("jsr GC_push_one");
  279.          asm("mov.l %d6,(%sp)"); asm("jsr GC_push_one");
  280.         asm("mov.l %d7,(%sp)"); asm("jsr GC_push_one");
  281.   
  282.         asm("addq.w &0x4,%sp");    /* put stack back where it was    */
  283. #        endif /* !__GNUC__ */
  284. #       endif /* M68K/SYSV */
  285.  
  286.  
  287. #     if defined(HP_PA) || defined(M88K) || defined(POWERPC) || (defined(I386) && defined(OS2))
  288.     /* Generic code                          */
  289.     /* The idea is due to Parag Patel at HP. */
  290.     /* We're not sure whether he would like  */
  291.     /* to be he acknowledged for it or not.  */
  292.     {
  293.         static jmp_buf regs;
  294.         register word * i = (word *) regs;
  295.         register ptr_t lim = (ptr_t)(regs) + (sizeof regs);
  296.  
  297.         /* Setjmp on Sun 3s doesn't clear all of the buffer.  */
  298.         /* That tends to preserve garbage.  Clear it.         */
  299.         for (; (char *)i < lim; i++) {
  300.             *i = 0;
  301.         }
  302. #        ifdef POWERPC
  303.         (void) setjmp(regs);
  304. #        else
  305.             (void) _setjmp(regs);
  306. #        endif
  307.         GC_push_all_stack((ptr_t)regs, lim);
  308.     }
  309. #     endif
  310.  
  311.       /* other machines... */
  312. #       if !(defined M68K) && !(defined VAX) && !(defined RT) 
  313. #    if !(defined SPARC) && !(defined I386) && !(defined NS32K)
  314. #    if !defined(HP_PA) && !defined(M88K) && !defined(POWERPC)
  315.         --> bad news <--
  316. #       endif
  317. #       endif
  318. #       endif
  319. }
  320.  
  321. /* On register window machines, we need a way to force registers into     */
  322. /* the stack.    Return sp.                        */
  323. # ifdef SPARC
  324.     asm("    .seg     \"text\"");
  325. #   ifdef SVR4
  326.       asm("    .globl    GC_save_regs_in_stack");
  327.       asm("GC_save_regs_in_stack:");
  328.       asm("    .type GC_save_regs_in_stack,#function");
  329. #   else
  330.       asm("    .globl    _GC_save_regs_in_stack");
  331.       asm("_GC_save_regs_in_stack:");
  332. #   endif
  333.     asm("    ta    0x3   ! ST_FLUSH_WINDOWS");
  334.     asm("    mov    %sp,%o0");
  335.     asm("    retl");
  336.     asm("    nop");
  337. #   ifdef SVR4
  338.       asm("    .GC_save_regs_in_stack_end:");
  339.       asm("    .size GC_save_regs_in_stack,.GC_save_regs_in_stack_end-GC_save_regs_in_stack");
  340. #   endif
  341. #   ifdef LINT
  342.     word GC_save_regs_in_stack() { return(0 /* sp really */);}
  343. #   endif
  344. # endif
  345.  
  346.  
  347. /* GC_clear_stack_inner(arg, limit) clears stack area up to limit and    */
  348. /* returns arg.  Stack clearing is crucial on SPARC, so we supply    */
  349. /* an assembly version that's more careful.  Assumes limit is hotter    */
  350. /* than sp, and limit is 8 byte aligned.                */
  351. #if defined(ASM_CLEAR_CODE) && !defined(THREADS)
  352. #ifndef SPARC
  353.     --> fix it
  354. #endif
  355. # ifdef SUNOS4
  356.     asm(".globl _GC_clear_stack_inner");
  357.     asm("_GC_clear_stack_inner:");
  358. # else
  359.     asm(".globl GC_clear_stack_inner");
  360.     asm("GC_clear_stack_inner:");
  361.     asm(".type GC_save_regs_in_stack,#function");
  362. # endif
  363.   asm("mov %sp,%o2");        /* Save sp    */
  364.   asm("add %sp,-8,%o3");    /* p = sp-8    */
  365.   asm("clr %g1");        /* [g0,g1] = 0    */
  366.   asm("add %o1,-0x60,%sp");    /* Move sp out of the way,    */
  367.                   /* so that traps still work.    */
  368.                   /* Includes some extra words    */
  369.                   /* so we can be sloppy below.    */
  370.   asm("loop:");
  371.   asm("std %g0,[%o3]");        /* *(long long *)p = 0    */
  372.   asm("cmp %o3,%o1");
  373.   asm("bgu loop    ");        /* if (p > limit) goto loop    */
  374.     asm("add %o3,-8,%o3");    /* p -= 8 (delay slot) */
  375.   asm("retl");
  376.     asm("mov %o2,%sp");        /* Restore sp., delay slot    */
  377.   /* First argument = %o0 = return value */
  378. #   ifdef SVR4
  379.       asm("    .GC_clear_stack_inner_end:");
  380.       asm("    .size GC_clear_stack_inner,.GC_clear_stack_inner_end-GC_clear_stack_inner");
  381. #   endif
  382.   
  383. # ifdef LINT
  384.     /*ARGSUSED*/
  385.     ptr_t GC_clear_stack_inner(arg, limit)
  386.     ptr_t arg; word limit;
  387.     { return(arg); }
  388. # endif
  389. #endif  
  390.